package javagamecontroller.activities.controllers;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import util.input.android.events.AndroidSensorEvent;
import javagamecontroller.activities.SelectController;
import javagamecontroller.connection.BluetoothMessenger;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.DialogFragment;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.Vibrator;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;


/**
 * This class represents a frame for all controllers. It will be up to
 * subclasses
 * of a controllerframe to set up specific views.
 * The controller frame will take care of creating the proper button manager,
 * setting up a wake lock, and accelerometer.
 * All android controllers should have a select button that allows the user to
 * change the controller they are using.
 * 
 * @author Ben Schwab, Lance
 * 
 */

// add motion listening capabilities here

public abstract class ControllerFrame extends Activity implements IPauseDialogListener {
    /**
     * Constant used to identify configuration settings.
     */
    public final static String ACCEL_CONFIG = "accel_config";
    protected static final String REFLECTION_ERROR =
            "There was an error instantiating your button layout.";
    private BluetoothMessenger myMessenger;
    private Vibrator myVibrator;

    private ButtonManager myButtonManager;
    private WakeLock myWakeLock;
    private SensorManager mySensorManager;
    private Sensor myAccelerometer;
    private boolean myAccelerometerEnabled;
    private boolean myDialogShowing = false;

    @Override
    public void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                                  WindowManager.LayoutParams.FLAG_FULLSCREEN);
        myMessenger = BluetoothMessenger.getInstance();
        myVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        myWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Tag");
        myWakeLock.acquire();
        setUpAccelerometer();

    }

    private void setUpAccelerometer () {
        Bundle extras = getIntent().getExtras();
        boolean accelEnabled = extras.getBoolean(ACCEL_CONFIG);
        if (accelEnabled) {
            loadAccelerometer();
        }

    }

    protected void initializeButtonManager (String buttonManagerClassName) {
        try {
            Class bManager = Class.forName(buttonManagerClassName);
            Class[] args = new Class[2];
            args[0] = ControllerFrame.class;
            args[1] = Vibrator.class;
            Constructor c = bManager.getConstructor(args);
            myButtonManager = (ButtonManager) c.newInstance(this, myVibrator);
        }

        // Print out any errors to your phone's error log.

        catch (ClassNotFoundException e) {
            Log.e(REFLECTION_ERROR, e.toString());
        }
        catch (InstantiationException e) {
            Log.e(REFLECTION_ERROR, e.toString());
        }
        catch (IllegalAccessException e) {
            Log.e(REFLECTION_ERROR, e.toString());
        }
        catch (NoSuchMethodException e) {
            Log.e(REFLECTION_ERROR, e.toString());
        }
        catch (IllegalArgumentException e) {
            Log.e(REFLECTION_ERROR, e.toString());
        }
        catch (InvocationTargetException e) {
            Log.e(REFLECTION_ERROR, e.toString());
        }

    }

    private void loadAccelerometer () {
        mySensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        myAccelerometer = mySensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mySensorManager.registerListener(myAccelerationListener, myAccelerometer,
                                         SensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    protected void onStop () {
        super.onStop();
        if (mySensorManager != null) {
            mySensorManager.unregisterListener(myAccelerationListener);
        }
    }

    @Override
    protected void onResume () {
        super.onResume();
        if (mySensorManager != null) {
            mySensorManager.registerListener(myAccelerationListener, myAccelerometer,
                                             SensorManager.SENSOR_DELAY_GAME);
        }
    }

    private SensorEventListener myAccelerationListener = new SensorEventListener() {

        @Override
        public void onAccuracyChanged (Sensor sensor, int accuracy) {

        }

        @Override
        public void onSensorChanged (SensorEvent event) {
            AndroidSensorEvent sensor = new AndroidSensorEvent(event.values);
            myMessenger.write(sensor);

        }

    };

    /**
     * Create the dialog to switch controllers
     */
    public void switchControllers () {
        if (!myDialogShowing) {
            showNoticeDialog();
        }
    }

    @TargetApi(11)
    /**
     * Show the notice dialog to switch controllers
     */
    public void showNoticeDialog () {
        // Create an instance of the dialog fragment and show it
        myDialogShowing = true;
        DialogFragment dialog = new PauseDialogFragment();
        dialog.show(getFragmentManager(), "PauseDialogFragment");
    }

    @TargetApi(11)
    @Override
    public void onDialogPositiveClick (DialogFragment dialog) {
        myDialogShowing = false;
        dialog.dismiss();
    }

    @Override
    @TargetApi(11)
    public void onDialogNegativeClick (DialogFragment dialog) {
        myDialogShowing = false;
        Intent i = new Intent(this, SelectController.class);
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        this.finish();
        startActivity(i);
    }

    @Override
    public void onPause () {
        super.onPause();

        if (myWakeLock != null) {

            try {
                myWakeLock.release();
            }
            catch (Throwable th) {
                // ignoring this exception, wakeLock was already
                // released
            }
        }

    }

    protected ButtonManager getButtonManager () {
        return myButtonManager;
    }

    protected Vibrator getVibrator () {
        return myVibrator;
    }

    protected BluetoothMessenger getMessenger () {
        return myMessenger;
    }

}
